﻿using Abp.Application.Services;
using Abp.Extensions;
using Abp.Localization;
using Abp.MultiTenancy;
using Abp.Runtime.Session;
using Mt.Site.Application.Localization.Dto;
using Mt.Site.Core.Base.Localization;
using Mt.Site.Core.MultiTenancy;
using Mt.Site.Core.MultiTenancy.Config;
using Mt.Site.Core.Url;
using Mt.Site.Core.Web;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Application.Localization
{
    public class LanguageFrontEndAppService : ApplicationService, ILanguageFrontEndAppService
    {
        private readonly IApplicationLanguageManager _applicationLanguageManager;
        private readonly ITenancyUrlConfig _tenancyUrlConfig;
        private readonly ITenancyNameCache _tenancyNameCache;
        private readonly ITenantStore _tenantStore;
        private readonly IUrlGetter _urlGetter;

        public LanguageFrontEndAppService(
            IApplicationLanguageManager applicationLanguageManager,
            ITenancyUrlConfig tenancyUrlConfig,
            ITenantStore tenantStore,
            ITenancyNameCache tenancyNameCache,
            IUrlGetter urlGetter)
        {
            _applicationLanguageManager = applicationLanguageManager;
            _tenancyUrlConfig = tenancyUrlConfig;
            _tenantStore = tenantStore;
            _tenancyNameCache = tenancyNameCache;
            _urlGetter = urlGetter;

            AbpSession = NullAbpSession.Instance;
        }
        public async Task<LanguageDto> GetCurrentLanguage()
        {
            var cultureName = AbpSession.CultureName();
            var tenantId = AbpSession.TenantId;
            string urlStr = "/";

            var context = _tenancyNameCache.HttpContext;
            if(context == null)
            {
                throw new Exception("不支持后台访问");
            }
            var urlReferrer = UrlChecker.GetRefererUrl(context.Request);
            if(urlReferrer!= null)
            {
                urlStr = urlReferrer.AbsolutePath;
            }

            var languages = await _applicationLanguageManager.GetLanguagesOfSingleTenantAsync(tenantId);
            if (languages.Count > 0)
            {
                var currentLanguage = languages.FirstOrDefault(l => l.Name == cultureName);
                if (currentLanguage == null)
                {
                    currentLanguage = languages.FirstOrDefault(l => cultureName.StartsWith(l.Name));
                }

                return new LanguageDto
                {
                    DisplayName = currentLanguage.DisplayName,
                    Name = currentLanguage.Name,
                    Icon = currentLanguage.Icon,
                    TenantId = currentLanguage.TenantId.Value,
                    Url = urlStr
                };
            }

            throw new Exception($"there is no languages for tenant:{tenantId}");
        }

        public async Task<IReadOnlyList<LanguageDto>> GetLanguages(GetLanguagesInput input)
        {
            if (input.AbsolutePath.IsNullOrEmpty())
            {
                var context = _tenancyNameCache.HttpContext;
                if (context == null)
                {
                    throw new Exception("不支持后台访问");
                }
                var urlReferrer = UrlChecker.GetRefererUrl(context.Request);
                if (urlReferrer != null)
                {
                    input.AbsolutePath = urlReferrer.AbsolutePath;
                }
            }

            var urlStrNoPrefix = "/";

            bool isHaveDiyRoute = false;
            if (input.AbsolutePath != null)
            {
                var cultureName = input.CultureName;
                var tenancyName = input.TenancyName;

                UrlChecker.CheckUrl(input.AbsolutePath, tenancyName, cultureName, out bool shouldRewritePath, out bool isIndex, out string regularUrlNoPrefix);
                //当前访问页面的链接
                var currentPageFullVisitUrl = $"/{tenancyName}/{cultureName}{regularUrlNoPrefix.RemovePostFix("/")}";

                using (_tenancyNameCache.Use(tenancyName, cultureName))
                {
                    var currentPageRealUrl = _urlGetter.DiyUrlToRealUrl(currentPageFullVisitUrl.ToLower(), out isHaveDiyRoute);
                    if (isHaveDiyRoute)
                    {
                        urlStrNoPrefix = currentPageRealUrl.Substring($"/{tenancyName}/{cultureName}".Length);
                    }
                    else
                    {
                        urlStrNoPrefix = currentPageFullVisitUrl.Substring($"/{tenancyName}/{cultureName}".Length);
                    }
                }
            }

            var result = new List<LanguageDto>();
            var defaultTenancyName = Tenant.DefaultTenantName;

            string thisUrl;

            //遍历配置文件中的每个分站
            foreach (var item in _tenancyUrlConfig.Config)
            {
                var tenantInfo = _tenantStore.Find(item.TenancyName);
                if (tenantInfo != null)
                {
                    //获取该分站的语种清单
                    var languages = await _applicationLanguageManager.GetLanguagesOfSingleTenantAsync(tenantInfo.Id);
                    foreach (var language in languages)
                    {
                        if (language.Name == item.CultureName)
                        {
                            var realUrl = $"/{tenantInfo.TenancyName}/{language.Name}{urlStrNoPrefix}";
                            using (_tenancyNameCache.Use(tenantInfo.TenancyName, language.Name))
                            {
                                var routeUrl = _urlGetter.RealUrlToDiyUrl(realUrl, out isHaveDiyRoute);
                                if (isHaveDiyRoute)
                                {
                                    if (item.ShouldCompareDomain)
                                    {
                                        thisUrl = $"{item.DomainNameAndDir}{routeUrl.Substring($"/{tenantInfo.TenancyName}/{language.Name}".Length)}";
                                    }
                                    else
                                    {
                                        thisUrl = $"{item.PrefixForComparison.RemovePostFix("/")}{routeUrl.Substring($"/{tenantInfo.TenancyName}/{language.Name}".Length)}";
                                    }
                                }
                                else
                                {
                                    if (item.ShouldCompareDomain)
                                    {
                                        thisUrl = $"{item.DomainNameAndDir}{realUrl.Substring($"/{tenantInfo.TenancyName}/{language.Name}".Length)}";
                                    }
                                    else
                                    {
                                        thisUrl = $"{item.PrefixForComparison.RemovePostFix("/")}{realUrl.Substring($"/{tenantInfo.TenancyName}/{language.Name}".Length)}";
                                    }
                                }

                                result.Add(new LanguageDto
                                {
                                    DisplayName = language.DisplayName,
                                    Name = language.Name,
                                    Icon = language.Icon,
                                    TenantId = language.TenantId.Value,
                                    Url = thisUrl,
                                    IsDefault = (item.TenancyName == defaultTenancyName),
                                    Region = item.Region,
                                    Order = item.Order
                                });
                            }
                        }
                    }
                }
            }

            foreach (var item in _tenancyUrlConfig.OtherConfig)
            {
                result.Add(new LanguageDto
                {
                    DisplayName = item.DisplayName,
                    Icon = item.Icon,
                    Url = item.Url,
                    Region = item.Region,
                    Order = item.Order
                });
            }
            return result.OrderByDescending(l => l.IsDefault).ThenBy(l => l.Region).ThenBy(l => l.Order).ToList();
        }
    }
}
